home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
cmln0686.arc
/
LERP.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-03-31
|
4KB
|
118 lines
page 58,132
; file: LERP.ASM
;
; LERP stands for Linear intERPolation.
; THIS ROUTINE ACCEPTS THREE SHORT INTEGET ARGUMENTS, IT
; MULTIPLYS THE FIRST TWO TOGETHER, THEN ADDS HALF OF THE
; THIRD ARGUMENT AND DIVIDES BY THE THIRD ARGUMENT.
;
; THE MULTIPLY IS A 16*16 GIVING 32 BITS, AND THE DIVIDE IS
; A 32/16 GIVING 16 BIT DIVIDE, SO NO OVERFLOW SHOULD HAPPEN.
; ADDING HALF OF THE DIVISOR RESULTS IN THE ANSWER BEING ROUNDED
; OFF AT 0.5. DIVIDING BY ZERO WILL RESULT IN AN ANSWER THAT IS
; +/- 32767 -- THE 16BIT INTEGER EQUIVALENT OF INFINITY.
;
; (c) Copyright 1984 by The Computer Entomologist
;
; Permission is hearby granted to use or distribute this software
;without any restrictions. You may make copies for yourself or your
;friends. You may include it in any hardware or software product that you
;sell for profit.
;
; This software is distributed as is, and is not guaranteed to work
;on any particular hardware/software configuration. Furthermore, no
;liability is granted with this software: the user takes responcibility for
;any damage this software may do to his system.
;
; Nasy notices aside, if you have any questions about this software, you
;can reach me at the address below. If you impliment any new features or
;find (and fix!) any bugs, I would be happy to hear from you.
;
; Mike Higgins
; The Computer Entomologist
; P.O. Box 197
; Duncans Mills, CA 95430
;
;PARAMETERS:
NUM=6 ;A NUMBER TO BE TRANSFORMED
MULT=8 ;THE AMOUNT TO MULTIPLY BY
DIVIS=10 ;THE AMOUNT TO DIVIDE BY
INCLUDE MODEL.H
INCLUDE PROLOGUE.H
PUBLIC LERP
LERP PROC FAR
PUSH BP ;DO THE NORMAL STACK FRAMING
MOV BP,SP
MOV AX,NUM[BP] ;GET THE FIRST ARGUMENT
XOR BH,BH ;BH WILL CONTAIN THE SIGN OF RESULT
OR AH,AH ;TAKE THE ABS OF 1ST ARGUMENT
JGE POS1
MOV BH,AH ;SAVE THE SIGN IN BH
NEG AX
POS1:
MOV CX,MULT[BP] ;GET THE 2ND ARGUMENT
OR CH,CH ;TAKE IT'S ABSULUTE VALUE
JGE POS2
XOR BH,CH ;BUT SAVE SIGN FIRST
NEG CX
POS2:
IMUL CX ;MULTIPLY BY THE 2ND ARGUMENT.
MOV CX,DIVIS[BP] ;GET THE THIRD ARGUMENT,
OR CX,CX ;CHECK IT TO SEE IF IT IS
JG POS3 ;POSITIVE, OR IF
JL NEG3 ;NEGATIVE.
INFINITY:
MOV AX,07FFFH ;IF ZERO, RETURN A LARGE NUMBER
JMP SIGN ;POSITIVE OR NEGATIVE INFINITY)
NEG3:
XOR BH,CH ;SAVE THE SIGN OF DIVISOR,
NEG CX ;AND MAKE IT POSITIVE
POS3:
IDIV CX ;FINALLY, DO THE DIVISION
SAR CX,1 ;AND DIVIDE DIVISOR BY 2
CMP CX,DX ;IS REMAINDER >= 1/2 DIVISOR?
JG SIGN ;NO.
INC AX ;YES, INCRIMENT RESULT.
SIGN: OR BH,BH ;CHECK THE SIGN OF THE RESULT
JGE DONE ;IF POSITIVE, YOU CAN QUIT
NEG AX ;ELSE MAKE THE RESULT NEGATIVE NOW
DONE:
POP BP
RET
LERP ENDP
;
; Can you beleive it? On the 8088/86/286 it is impossible
; to test for integer overflow on a divide! The only way to detect
; this error is to catch divide-by-zero interupts! So I wrote the
; following two routines: OVRSET() must be called once by your main
; program, and it points the divide overflow vector at DIVOVR. This
; version of DIVOVR always assumes a 32 by 16 bit divide, and just
; loads AX and DX with "infinity" with no remainder.
;
DIVOVR PROC FAR ;ROUTINE TO PROCESS DIVISION OVERFLOW ERRORS
MOV AX,07FFFH ;CHANGE AX TO A LARGE NUMBER
XOR DX,DX ;ZERO DX (ASSUME 16 BIT DIVIDE)
IRET ;AND RETURN, THAT'S ALL.
DIVOVR ENDP
PUBLIC OVRSET
OVRSET PROC FAR ;ROUTINE TO SET DIVISION OVERFLOW INTERUPT VECTOR
PUSH DS
MOV AX,CS ;USE CURRENT CODE SEGMENT
MOV DS,AX
MOV DX,OFFSET @CODE:DIVOVR
MOV AX,02500H ;ASK TO LOAD THE DIVIDE BY ZERO VECTOR
INT 21H
POP DS
RET
OVRSET ENDP
INCLUDE EPILOGUE.H
END